#! /usr/bin/python
import os
import sys
import ConfigParser
import logging.handlers
from backupManager.enum import AEnums
import datetime
import Pyro4
import traceback
from backupManager.mixins import backupMixin
import logging

class LoggerWriter:
    def __init__(self, level, logger):
        self.level = level
        self.logger = logger

    def write(self, message):
        if message != '\n':
            self.logger.log(self.level, message)


class indexServer(object):
    def __init__(self, indexer):
        self.indexer = indexer

    def index(self, commDict):
        self.indexer.count = 0
        return self.indexer.indexDrive(commDict)

    def count(self):
        return self.indexer.count


class Indexer(backupMixin):
    def __init__(self):
        self.count = 0
        self.logger = logging.getLogger('AnyBackup')
        self.formatter = logging.Formatter(fmt='%(asctime)s - %(levelname)s - %(funcName)s - %(message)s')
        self.handler = logging.handlers.TimedRotatingFileHandler('/var/log/AnyBackup.log', when='D',
                                                                 interval=1, backupCount=5)
        self.handler.setFormatter(self.formatter)
        self.logger.addHandler(self.handler)
        self.logger.setLevel(logging.DEBUG)
        sys.stdout = LoggerWriter(logging.INFO, self.logger)
        sys.stderr = LoggerWriter(logging.ERROR, self.logger)

    def indexDrive(self, commDict):
        self.logger.info('Received index request:')
        self.logger.info(str(datetime.datetime.now()))
        self.logger.info(commDict)
        if not os.path.exists(commDict[AEnums.REMOTEPATH]):
            return AEnums.NOTEXIST
        validext = self.compileValidExt(commDict[AEnums.VALIDEXTS])
        skip = self.compileSkipList(commDict[AEnums.SKIPLIST])
        root = []
        files = []
        # noinspection PyBroadException
        try:
            for path in commDict[AEnums.PATHS]:
                path = path.strip(commDict[AEnums.SEP])
                path = path.replace(commDict[AEnums.SEP], os.sep)
                path = unicode(path)
                newFile = self.index(path, validext, skip, files, root=True, commDict=commDict)
                files.append(newFile)
                root.append(newFile[AEnums.ID])
        except:
            self.logger.error(traceback.format_exc())
        self.logger.info('Done indexing!')
        self.logger.info(str(datetime.datetime.now()))
        return {
            AEnums.FILES: files,
            AEnums.ROOT: root,
        }

    def index(self, path, validext, skip, filesIn, root=False, commDict=None):
        """

        :param path: directory path to index
        :param validext: list of valid extensions to look for
        :param skip: list of regular expressions to skip
        :param filesIn: list object to append new files to
        :param root: is this a root directory?
        :param commDict: a dictionary filled with path information (i.e. local -> remote mapping)
        :return: a file descriptor representing the directory
        """
        self.count = len(filesIn)
        dirName = os.path.join(commDict[AEnums.REMOTEPATH], path)
        dirName = dirName.rstrip(os.sep)
        if not os.path.isdir(dirName):
            return None
        files = self.getIndexFiles(dirName)
        fd = self.createDirRef(commDict, path, dirName, root)
        passedFiles = []
        for foundFile in files[:]:
            try:
                if not self.shouldProcess(dirName, foundFile, skip, validext):
                    continue
            except UnicodeDecodeError:
                self.logger.error('Could not process file %s, %s', dirName, foundFile.decode('utf-8'))
                continue
            if os.path.isdir(os.path.join(dirName, foundFile)):
                newFile = self.index(os.path.join(path, foundFile), validext, skip, filesIn, False, commDict)
            else:
                newFile = self.createFileRef(commDict, path, dirName, foundFile)
            if newFile:
                newFile[AEnums.PARENT] = fd[AEnums.ID]
                passedFiles.append(newFile)
        if not passedFiles and not root:
            return None
        [filesIn.append(x) for x in passedFiles]
        return fd


def main():
    config = ConfigParser.SafeConfigParser({'pyro-port': 6500})
    config.read('/etc/anybackupserver.conf')
    port = int(config.get('anybackup', 'pyro-port'))
    i = indexServer(Indexer())
    Pyro4.Daemon.serveSimple(
        {
            i: "anybackup.indexserver"
        },
        ns=False, port=port, host='')

if __name__ == "__main__":
    main()
